<!--
 * ssh终端首页
 *
 * @author Junpeng.Li
 * @date 2022-04-08 22:58
-->
<template>
    <div style="width: 100%;height: 100%;">
        <!-- 头部工具栏 -->
        <top-tool
                :terminals="$refs.terminal"
                :tab-active-name="terminalTabs.active"
                :compile-com="compileCom()"
                :fast-cmd-com="fastCmdCom()"
                @connect="connect"
        />

        <div class="terminal-tabs" :style="{
            height: `calc(100% - ${terminalTabs.height}px)`
        }">
            <el-tabs v-model="terminalTabs.active" type="card" style="height: 100%;">
                <el-tab-pane v-for="(item, index) in terminalTabs.tabs" :key="item._key" :name="`tab-${index}`">
                    <div slot="label">
                        <div class="tab-status unconn"></div>
                        <span>{{item.name}}</span>

                        <!-- 操作菜单 -->
                        <tab-menu
                                v-if="`tab-${index}` === terminalTabs.active && item.host"
                                :terminals="$refs.terminal"
                                :key="item._key"
                                :conn-info="item"
                                @insert="addTab"
                                @remove="deleteTab"
                                @rename="renameTabName"/>
                    </div>

                    <!-- terminal终端 -->
                    <x-terminal :key="item._key" ref="terminal" :conn-info="item" :is-active="termIsActive"/>
                </el-tab-pane>
            </el-tabs>
        </div>

        <!-- 快速命令窗口组件 -->
        <fast-cmd
            ref="fastCmdRef"
            v-if="fastCmd.visible"
            :terminals="$refs.terminal"
            :index="tabActiveIndex"
        />

        <!-- 撰写窗口组件 -->
        <compile
                title="撰写命令"
                ref="compileRef"
                v-if="compile.visible"
                :terminals="$refs.terminal"
                :index="tabActiveIndex"
        />
    </div>
</template>

<script>
    import TopTool from './top-tool'
    import XTerminal from '@/components/xterm-terminal'
    import TabMenu from './tab-menu'

    import Compile from '@/components/compile/index'
    import {getSettings, setSettings} from "@/api/compile"

    import FastCmd from '@/components/fast-cmd/index'
    import { getStting as getFastCmdSetting, setSetting as setFastCmdSetting } from "@/api/fast-cmd.api"

    import {v1 as uuidv1} from 'uuid'

    export default {
        name: "ssh",

        components: {
            TopTool,
            XTerminal,
            TabMenu,
            Compile,
            FastCmd
        },

        data() {
            return {
                /**
                 * 会话列表的tab对象
                 */
                terminalTabs: {

                    active: 'tab-0',

                    tabs: [{
                        name: '新建会话',
                        host: null,
                        port: 22
                    }],

                    // tab组件中，height样式为calc(100% - ${height}px)，其中${height}的height就是该字段值，默认为54
                    height: 54

                },

                /**
                 * 撰写窗口组件对象
                 */
                compile: {
                    visible: false
                },

                /**
                 * 快速命令组件
                 */
                fastCmd: {
                    visible: false
                }
            }
        },

        watch: {
            /**
             * 切换tab标签时，重置terminal大小，防止浏览器窗口大小改变时除当前外其他的tab标签内的terminal大小计算错误
             */
            'terminalTabs.active'(name) {
                const terminals = this.$refs.terminal

                // 如果首次创建新的连接，就不需要重置大小，因为默认就已经就算大小了
                if (terminals.length !== this.terminalTabs.tabs.length) {
                    return
                }

                this.resizeTerminal(name)
            }
        },

        mounted() {
            this.compileCom().initSetting()
            this.fastCmdCom().initSetting()
        },

        methods: {

            /**
             * 处理data，给data对象添加_key属性
             */
            processData(_data) {
                const data = JSON.parse(JSON.stringify(_data))
                data._key = uuidv1()

                return data
            },

            /**
             * 添加一个新的连接
             */
            connect(_data) {
                const data = this.processData(_data)

                if (this.tabsLen === 1 && !this.terminalTabs.tabs[0].host) {
                    this.terminalTabs.tabs = []
                }

                setTimeout(() => {
                    this.terminalTabs.tabs.push(data)
                    this.terminalTabs.active = `tab-${this.tabsLen - 1}`
                }, 100)
            },

            /**
             * 复制一个Tab页
             */
            addTab(_data) {
                const data = this.processData(_data)
                data.name = data.name + '_copy'
                this.connect(data)
            },

            /**
             * 删除一个Tab页
             */
            deleteTab(index) {
                this.terminalTabs.tabs.splice(index, 1)

                if (this.terminalTabs.tabs.length === 0) {
                    this.terminalTabs.tabs.push({
                        _key: uuidv1(),
                        name: '新建会话',
                        host: null,
                        port: 22
                    })

                    this.terminalTabs.active = 'tab-0'
                } else if (this.terminalTabs.tabs.length === 1) {
                    this.terminalTabs.active = 'tab-0'
                } else if (this.terminalTabs.tabs.length === index) {
                    this.terminalTabs.active = `tab-${this.terminalTabs.tabs.length - 1}`
                }
            },

            /**
             * 重命名标签名称
             */
            renameTabName(name, index) {
                this.terminalTabs.tabs[index].name = name
            },

            /**
             * 判断指定终端是否是激活状态
             * @param termKey terminal组件的key
             * @return {boolean}
             *   - true：指定的终端是当前激活的
             *   - false: 指定的终端不是当前激活的
             */
            termIsActive(termKey) {
                const index = parseInt(this.terminalTabs.active.split('-')[1])
                const terminal = this.$refs.terminal[index]
                return terminal.$props.connInfo._key === termKey
            },

            /**
             * 重置指定tab中的终端尺寸
             * @param tabName tab中的name属性值
             */
            resizeTerminal(tabName) {
                this.$nextTick(() => {
                    const index = parseInt(tabName.split('-')[1])
                    this.$refs.terminal[index].resize()
                })
            },

            /**
             * 设置tab的height，这里的height是calc(100% - ${height}px)中的${height}
             */
            setTabHeight(height, isResize = true) {
                if (typeof height !== 'number') {
                    return
                }

                this.terminalTabs.height += height

                if (isResize) {
                    this.resizeTerminal(this.terminalTabs.active)
                }
            },

            /**
             * 撰写窗口组件的相关方法
             */
            compileCom() {
                const _this = this

                return {

                    /**
                     * 打开撰写窗口
                     */
                    open() {
                        _this.compile.visible = true
                        _this.$nextTick(() => {
                            _this.setTabHeight(_this.$refs.compileRef.getHeight())
                            setSettings('visible', true)
                        })
                    },

                    /**
                     * 关闭撰写窗口
                     */
                    close() {
                        _this.setTabHeight(0 - _this.$refs.compileRef.getHeight())
                        _this.compile.visible = false
                        setSettings('visible', false)
                    },

                    /**
                     * 获取撰写窗口的打开状态
                     */
                    getStatus() {
                        return _this.compile.visible
                    },

                    /**
                     * 初始化撰写窗口的设置
                     */
                    initSetting() {
                        if (getSettings().visible) {
                            this.open()
                        }
                    }

                }

            },

            /**
             * 快速命令窗口组件相关的方法
             */
            fastCmdCom() {
                const _this = this

                return {
                    /**
                     * 打开快速命令窗口
                     */
                    open() {
                        _this.fastCmd.visible = true

                        _this.$nextTick(() => {
                            const height = _this.$refs.fastCmdRef.getHeight()
                            _this.setTabHeight(height)
                            setFastCmdSetting('visible', true)
                        })
                    },

                    /**
                     * 关闭快速命令窗口
                     */
                    close() {
                        const height = _this.$refs.fastCmdRef.getHeight()
                        _this.setTabHeight(0 - height)
                        setFastCmdSetting('visible', false)

                        _this.fastCmd.visible = false
                    },

                    /**
                     * 获取快速命令窗口的打开状态
                     */
                    getStatus() {
                        return _this.fastCmd.visible
                    },

                    /**
                     * 初始化快速命令的设置
                     */
                    initSetting() {
                        const setting = getFastCmdSetting()
                        if (setting.visible) {
                            this.open()
                        }
                    }
                }
            }

        },

        computed: {
            /**
             * tab页的数量
             * @returns {number} 终端的数量
             */
            tabsLen() {
                return this.terminalTabs.tabs.length
            },

            /**
             * 当前tab页被激活的索引
             * @returns {number}
             */
            tabActiveIndex() {
                return parseInt(this.terminalTabs.active.split('-')[1])
            }
        }
    }
</script>

<style lang="scss" scoped>

    .terminal-tabs {
        width: calc(100% - 20px);
        height: calc(100% - 54px);
        padding: 0 10px;

        .tab-status {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            float: left;
            margin-top: 15px;
            margin-right: 10px;

            &.unconn {
                background-color: red;
            }

            &.conn {
                background-color: #3aff44;
            }
        }
    }

    /* 目的是让高度自适应以后容易计算出terminal的行数 */
    .el-tabs > > > .el-tabs__content {
        height: calc(100% - 56px);

        .el-tab-pane {
            height: 100%;
        }
    }

</style>
